package com.company;

//https://blog.csdn.net/linhaiyun_ytdx/article/details/78887658

/*  volatile关键字的主要作用是使变量在多个线程间可见*/
//代码分析
//        在java中,每一个线程都会有一块工作内存区,其中存放着所有线程共享的主内存中的变量值的拷贝.
//        当线程执行时,它在自己的工作内存区中操作这些变量.为了存取一个共享的变量,
//        一个线程通常先获取锁定并去清除它的内存工作区,把这些共享变量从所有线程的共享内存区中正确地装入到他自己所在工作内存区中,
//        当线程解锁时保证该工作内存区中变量的值写回到共享内存中.
//
//              一个线程可以执行的操作有使用(use),赋值(assign),装载(load),存储(store),锁定(lock),解锁(unlock)
//
//              而主内存可以执行的操作有读(Read),写(write),锁定(lock),解锁(unlock),每个操作都是原子的
//
//              volatile的作用就是强制线程到主内存(共享内存)里去读取变量,而不去线程工作内存区里去读取,
//              从而实现了多个线程间的变量可见,也就是满足线程安全的可见性

/*import java.util.concurrent.atomic.AtomicInteger;

public class C08volatileANDatomic extends Thread  {
    //如果此处不使用volatile关键字,那么程序执行结束,线程也不会终止,因为线程的运行取值是在内存区,和程序变量的定义无关
    private volatile boolean isRunning = true;
    private void setRunning(boolean isRunning){
        this.isRunning = isRunning;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("进入run方法...");
        while(isRunning == true){
            boolean a = isRunning;
        }
        System.out.println("线程终止...");
    }

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        C08volatileANDatomic rt = new C08volatileANDatomic();
        rt.start();
        Thread.sleep(3000);
        rt.setRunning(false);
        System.out.println("isRunning的值已经被设置了false");
        Thread.sleep(1000);
        System.out.println(rt.isRunning);
    }

}*/


import java.util.concurrent.atomic.AtomicInteger;

/**
 * volatile关键字的非原子性
 * @author lhy
 * @time   2017.12.23
 *
 */
//原子操作可以是一个步骤，也可以是多个操作步骤，但是其顺序不可以被打乱，也不可以被切割而只执行其中的一部分。

public class C08volatileANDatomic extends Thread {

   //	private static volatile int count;
    private static AtomicInteger count = new AtomicInteger(0);
    private void addCount(){
        for(int i=0; i<1000; i++){
	//		count++;
            // 当正在执行累加操作的时候如果CPU进行切换
            //		累加操作被分割了（本次累加操作全部没有执行完成）。
            //		这个时候原子性被破坏 。
//			正确结果应该是=10000
// 下面 最大数并没有得到10000
//            Thread-0----1000
//            Thread-6----3000
//            Thread-2----2000
//            Thread-3----4000
//            Thread-7----5000
//            Thread-1----6000
//            Thread-4----7000
//            Thread-8----8000
//            Thread-9----9232
//            Thread-5----9232
// 用原子类型保证数据累加到10000
            count.incrementAndGet();

        }
         System.out.println(this.getName()+"----"+count);
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        addCount();
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        C08volatileANDatomic[] arr = new C08volatileANDatomic [20];
        for(int i = 0 ; i<20; i++){
            arr[i] = new C08volatileANDatomic();
        }
        for(int i=0 ; i<20 ; i++){
            arr[i].start();
        }
    }

}

